package com.lcf.app.jwt.config;

import cn.hutool.core.bean.BeanUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.lcf.app.jwt.exception.MyTokenException;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import java.util.*;


/**
 * @author ChenFei
 * @date 2022/1/18
 */
@Setter
@Getter
@Configuration
@ConfigurationProperties(prefix = "jwt.config")
public class JwtHelper {

    private static final String JWT_DATA = "JWT_DATA";

    //jwt加密密匙
    private String secret = UUID.randomUUID().toString();
    //保存在请求头中的header名称
    private String headerName = "Authorization";
    //路径白名单
    private List<String> excludePath = new ArrayList<>();
    //默认过期时间30分钟
    private Long expireTime = 1000 * 30 * 30L;

    public String getToken(Object data) {
        return JWT.create()
                //设置token过期时间
                .withExpiresAt(new Date(System.currentTimeMillis() + expireTime))
                //.withSubject()
                //用户
                //.withAudience()
                //token签发人
                //.withIssuer("");
                //.withArrayClaim("ROLE",new String[]{"USER"});
                //生效时间
                //.withNotBefore()
                //自定义字段
                //.withClaim()
                .withClaim(JWT_DATA, BeanUtil.beanToMap(data))
                //加密方式及密匙设置
                .sign(getAlgorithm());
    }

    /**
     * 验证token，并返回
     *
     * @param token
     * @return
     */
    public <T> T verify(String token, Class<T> clazz) throws MyTokenException {
        try {
            DecodedJWT verify = JWT.require(getAlgorithm()).build().verify(token);
            Map map = verify.getClaim(JWT_DATA).as(Map.class);
            return BeanUtil.toBean(map, clazz);
        } catch (TokenExpiredException expiredException) {
            throw new MyTokenException("token已过期");
        } catch (Exception e) {
            throw new MyTokenException("token异常");
        }
    }

    public Map<String, Claim> get(String token) {
        return JWT.decode(token).getClaims();
    }

    private Algorithm getAlgorithm() {
        return Algorithm.HMAC256(secret);
    }
}
